package com.beauty.order.service.impl;

import com.beauty.order.dto.OrderRequest;
import com.beauty.order.dto.OrderResponse;
import com.beauty.order.dto.PageResponse;
import com.beauty.order.entity.Order;
import com.beauty.order.entity.OrderItem;
import com.beauty.order.repository.OrderRepository;
import com.beauty.order.server.KafkaProducerService;
import com.beauty.order.service.OrderIntegrationService;
import com.beauty.order.service.OrderService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.criteria.Predicate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    KafkaProducerService kafkaProducerService;


    private final OrderRepository orderRepository;
    private final OrderIntegrationService orderIntegrationService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    @Transactional
    public OrderResponse createOrder(OrderRequest orderRequest) throws JsonProcessingException {
        log.info("【订单服务】开始创建订单，客户ID: {}", orderRequest.getCustomerId());

        // 检查和预留库存
        for (OrderRequest.OrderItemRequest itemRequest : orderRequest.getOrderItems()) {
            log.info("【订单服务】处理订单项: 产品ID={}, 名称={}, 数量={}",
                    itemRequest.getProductId(), itemRequest.getProductName(), itemRequest.getQuantity());

            // 检查库存
            log.info("【订单服务】开始检查产品[{}]库存", itemRequest.getProductId());
            if (!orderIntegrationService.checkProductInventory(itemRequest.getProductId(), itemRequest.getQuantity())) {
                log.error("【订单服务】产品[{}]库存不足", itemRequest.getProductId());
                throw new RuntimeException("产品 " + itemRequest.getProductId() + " 库存不足");
            }

            // 预留库存
            log.info("【订单服务】开始预留产品[{}]库存", itemRequest.getProductId());
            if (!orderIntegrationService.reserveInventory(itemRequest.getProductId(), itemRequest.getQuantity())) {
                log.error("【订单服务】预留产品[{}]库存失败", itemRequest.getProductId());
                throw new RuntimeException("预留产品 " + itemRequest.getProductId() + " 库存失败");
            }
        }

        log.info("【订单服务】所有产品库存检查和预留成功，开始创建订单记录");
        Order order = new Order();
        order.setOrderNumber(generateOrderNumber());
        order.setCustomerId(orderRequest.getCustomerId());
        order.setShippingCost(orderRequest.getShippingCost() != null ? orderRequest.getShippingCost() : BigDecimal.ZERO);
        order.setTaxAmount(orderRequest.getTaxAmount() != null ? orderRequest.getTaxAmount() : BigDecimal.ZERO);
        order.setPaymentMethod(orderRequest.getPaymentMethod());
        order.setShippingMethod(orderRequest.getShippingMethod());
        order.setShippingAddress(orderRequest.getShippingAddress());
        order.setBillingAddress(orderRequest.getBillingAddress());
        order.setNotes(orderRequest.getNotes());
        order.setStatus(Order.OrderStatus.PENDING);
        order.setOrderDate(LocalDateTime.now());

        List<OrderItem> orderItems = new ArrayList<>();
        BigDecimal totalAmount = BigDecimal.ZERO;

        for (OrderRequest.OrderItemRequest itemRequest : orderRequest.getOrderItems()) {
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(itemRequest.getProductId());
            orderItem.setProductName(itemRequest.getProductName());
            orderItem.setProductImage(itemRequest.getProductImage());
            orderItem.setQuantity(itemRequest.getQuantity());
            orderItem.setUnitPrice(itemRequest.getUnitPrice());
            orderItem.setDiscountAmount(itemRequest.getDiscountAmount() != null ? itemRequest.getDiscountAmount() : BigDecimal.ZERO);

            BigDecimal itemTotal = itemRequest.getUnitPrice().multiply(BigDecimal.valueOf(itemRequest.getQuantity()));
            if (itemRequest.getDiscountAmount() != null) {
                itemTotal = itemTotal.subtract(itemRequest.getDiscountAmount());
            }
            orderItem.setSubtotal(itemTotal);

            orderItem.setSku(itemRequest.getSku());

            // 处理options字段 - 将Map转换为JSON字符串
            if (itemRequest.getOptions() != null) {
                try {
                    String optionsJson = objectMapper.writeValueAsString(itemRequest.getOptions());
                    orderItem.setOptions(optionsJson);
                } catch (JsonProcessingException e) {
                    log.error("序列化options失败", e);
                    orderItem.setOptions(null);
                }
            }

            orderItems.add(orderItem);
            totalAmount = totalAmount.add(itemTotal);
        }

        // 添加运费和税费
        totalAmount = totalAmount.add(order.getShippingCost()).add(order.getTaxAmount());
        order.setTotalAmount(totalAmount);
        order.setOrderItems(orderItems);

        Order savedOrder = orderRepository.save(order);
        log.info("【订单服务】订单创建成功，订单号: {}, ID: {}", order.getOrderNumber(), order.getId());
        String s = objectMapper.writeValueAsString(order);
        kafkaProducerService.sendMessage("user-messages","下单成功",s);
        return OrderResponse.fromEntity(savedOrder);
    }

    @Override
    public OrderResponse getOrderById(Long id) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在，ID: " + id));
        return OrderResponse.fromEntity(order);
    }

    @Override
    public OrderResponse getOrderByOrderNumber(String orderNumber) {
        Order order = orderRepository.findByOrderNumber(orderNumber)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在，订单号: " + orderNumber));
        return OrderResponse.fromEntity(order);
    }

    @Override
    public List<OrderResponse> getOrdersByCustomerId(String customerId) {
        return orderRepository.findByCustomerId(customerId)
                .stream()
                .map(OrderResponse::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<OrderResponse> getOrdersByStatus(Order.OrderStatus status) {
        return orderRepository.findByStatus(status)
                .stream()
                .map(OrderResponse::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<OrderResponse> getOrdersByDateRange(LocalDateTime start, LocalDateTime end) {
        return orderRepository.findByOrderDateBetween(start, end)
                .stream()
                .map(OrderResponse::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<OrderResponse> getAllOrders() {
        return orderRepository.findAll()
                .stream()
                .map(OrderResponse::fromEntity)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public OrderResponse updateOrderStatus(Long id, Order.OrderStatus status) {
        log.info("【订单服务】开始更新订单状态, ID: {}, 新状态: {}", id, status);
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在，ID: " + id));

        log.info("【订单服务】订单当前状态: {}, 订单号: {}", order.getStatus(), order.getOrderNumber());
        order.setStatus(status);

        // 根据状态更新相应的日期
        switch (status) {
            case PAID:
                log.info("【订单服务】订单已支付，设置支付时间");
                order.setPaymentDate(LocalDateTime.now());
                break;
            case SHIPPED:
                log.info("【订单服务】订单发货处理开始");
                order.setShippingDate(LocalDateTime.now());

                // 减少库存（从预留状态转为实际消耗）
                log.info("【订单服务】开始处理订单中的{}个产品项的库存扣减", order.getOrderItems().size());
                for (OrderItem item : order.getOrderItems()) {
                    log.info("【订单服务】处理产品[{}]库存扣减，数量: {}", item.getProductId(), item.getQuantity());
                    if (!orderIntegrationService.reduceInventory(item.getProductId(), item.getQuantity())) {
                        log.error("【订单服务】减少产品[{}]库存失败", item.getProductId());
                        // 不抛出异常，防止影响订单状态更新
                    }
                }

                // 注意：物流单的创建应在前端选择承运商后通过专门的API调用创建
                // 这里不再自动创建物流单
                break;
            case DELIVERED:
                log.info("【订单服务】订单已送达，设置送达时间");
                order.setDeliveryDate(LocalDateTime.now());
                break;
            case CANCELLED:
                log.info("【订单服务】订单取消处理开始");
                // 如果订单取消，释放预留的库存
                log.info("【订单服务】开始处理订单中的{}个产品项的库存释放", order.getOrderItems().size());
                for (OrderItem item : order.getOrderItems()) {
                    log.info("【订单服务】处理产品[{}]预留库存释放，数量: {}", item.getProductId(), item.getQuantity());
                    if (!orderIntegrationService.releaseInventory(item.getProductId(), item.getQuantity())) {
                        log.error("【订单服务】释放产品[{}]预留库存失败", item.getProductId());
                        // 不抛出异常，防止影响订单状态更新
                    }
                }
                break;
            default:
                log.info("【订单服务】订单状态更新为: {}", status);
                break;
        }

        Order updatedOrder = orderRepository.save(order);
        log.info("【订单服务】订单状态更新成功，ID: {}, 订单号: {}, 新状态: {}",
                updatedOrder.getId(), updatedOrder.getOrderNumber(), updatedOrder.getStatus());
        return OrderResponse.fromEntity(updatedOrder);
    }

    @Override
    @Transactional
    public OrderResponse updateTrackingNumber(Long id, String trackingNumber) {
        Order order = orderRepository.findById(id)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在，ID: " + id));

        order.setTrackingNumber(trackingNumber);
        Order updatedOrder = orderRepository.save(order);
        return OrderResponse.fromEntity(updatedOrder);
    }

    @Override
    @Transactional
    public void deleteOrder(Long id) {
        if (!orderRepository.existsById(id)) {
            throw new EntityNotFoundException("订单不存在，ID: " + id);
        }
        orderRepository.deleteById(id);
    }

    @Override
    public PageResponse<OrderResponse> getOrdersPage(Pageable pageable) {
        log.info("【订单服务】获取订单分页数据，页码: {}, 每页大小: {}", pageable.getPageNumber(), pageable.getPageSize());
        Page<Order> page = orderRepository.findAll(pageable);
        Page<OrderResponse> responsePage = page.map(OrderResponse::fromEntity);
        return PageResponse.fromPage(responsePage);
    }

    @Override
    public PageResponse<OrderResponse> getOrdersByCustomerIdPage(String customerId, Pageable pageable) {
        log.info("【订单服务】获取客户[{}]订单分页数据，页码: {}, 每页大小: {}",
                customerId, pageable.getPageNumber(), pageable.getPageSize());
        Page<Order> page = orderRepository.findByCustomerId(customerId, pageable);
        Page<OrderResponse> responsePage = page.map(OrderResponse::fromEntity);
        return PageResponse.fromPage(responsePage);
    }

    @Override
    public PageResponse<OrderResponse> getOrdersByStatusPage(Order.OrderStatus status, Pageable pageable) {
        log.info("【订单服务】获取状态为[{}]的订单分页数据，页码: {}, 每页大小: {}",
                status, pageable.getPageNumber(), pageable.getPageSize());
        Page<Order> page = orderRepository.findByStatus(status, pageable);
        Page<OrderResponse> responsePage = page.map(OrderResponse::fromEntity);
        return PageResponse.fromPage(responsePage);
    }

    @Override
    public PageResponse<OrderResponse> getOrdersByDateRangePage(LocalDateTime start, LocalDateTime end, Pageable pageable) {
        log.info("【订单服务】获取日期范围[{} - {}]内的订单分页数据，页码: {}, 每页大小: {}",
                start, end, pageable.getPageNumber(), pageable.getPageSize());
        Page<Order> page = orderRepository.findByOrderDateBetween(start, end, pageable);
        Page<OrderResponse> responsePage = page.map(OrderResponse::fromEntity);
        return PageResponse.fromPage(responsePage);
    }

    @Override
    public PageResponse<OrderResponse> searchOrders(String keyword, Pageable pageable) {
        log.info("【订单服务】执行关键字模糊查询: keyword={}", keyword);
        if (keyword == null || keyword.trim().isEmpty()) {
            return getOrdersPage(pageable);
        }

        Page<Order> page = orderRepository.searchByKeyword(keyword.trim(), pageable);
        Page<OrderResponse> responsePage = page.map(OrderResponse::fromEntity);
        log.info("【订单服务】模糊查询结果: 找到{}条记录", page.getTotalElements());
        return PageResponse.fromPage(responsePage);
    }
    @Override
    @Transactional
    public Order updateOrderStatusByOrderNumber(String orderNumber, String status) {
        log.info("【订单服务】通过订单号更新订单状态: orderNumber={}, status={}", orderNumber, status);
        Order order = orderRepository.findByOrderNumber(orderNumber)
                .orElseThrow(() -> new EntityNotFoundException("订单不存在，订单号: " + orderNumber));

        order.setStatus(Order.OrderStatus.valueOf(status));

        // 如果状态为已支付，设置支付时间
        if ("PAID".equals(status)) {
            log.info("【订单服务】订单已支付，设置支付时间: {}", orderNumber);
            order.setPaymentDate(LocalDateTime.now());
        }

        return orderRepository.save(order);
    }
    @Override
    public PageResponse<OrderResponse> advancedSearch(String orderNumber, String customerId,
                                                    String trackingNumber, String notes,
                                                    String shippingAddress, Pageable pageable) {
        log.info("【订单服务】执行高级搜索: orderNumber={}, customerId={}, trackingNumber={}, notes={}, shippingAddress={}",
                orderNumber, customerId, trackingNumber, notes, shippingAddress);

        Specification<Order> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (StringUtils.hasText(orderNumber)) {
                predicates.add(criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("orderNumber")),
                    "%" + orderNumber.toLowerCase() + "%"));
            }

            if (StringUtils.hasText(customerId)) {
                predicates.add(criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("customerId")),
                    "%" + customerId.toLowerCase() + "%"));
            }

            if (StringUtils.hasText(trackingNumber)) {
                predicates.add(criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("trackingNumber")),
                    "%" + trackingNumber.toLowerCase() + "%"));
            }

            if (StringUtils.hasText(notes)) {
                predicates.add(criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("notes")),
                    "%" + notes.toLowerCase() + "%"));
            }

            if (StringUtils.hasText(shippingAddress)) {
                predicates.add(criteriaBuilder.like(
                    criteriaBuilder.lower(root.get("shippingAddress")),
                    "%" + shippingAddress.toLowerCase() + "%"));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };

        Page<Order> page = orderRepository.findAll(spec, pageable);
        Page<OrderResponse> responsePage = page.map(OrderResponse::fromEntity);
        log.info("【订单服务】高级搜索结果: 找到{}条记录", page.getTotalElements());
        return PageResponse.fromPage(responsePage);
    }

    private String generateOrderNumber() {
        return "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
    }

    @Override
    public Order getOrderByIdEntity(Long id) {
        return orderRepository.findById(id).orElse(null);
    }
}
